﻿#include "flutter_blue_device_agent.h"
#include "flutter_blue_utils.h"
#include <stdexcept>

using namespace winrt;
using namespace Windows::Devices::Bluetooth;
using namespace Windows::Devices::Bluetooth::GenericAttributeProfile;

// 构造函数
BluetoothDeviceAgent::BluetoothDeviceAgent(BluetoothLEDevice device, event_token connectionStatusChangedToken, MaxPduSizeChangedCallback callback)
        : device(device),
          connectionStatusChangedToken(connectionStatusChangedToken),
          onMtuChangeCallback(callback) {}

// 析构函数
BluetoothDeviceAgent::~BluetoothDeviceAgent() {
    Close();
}

// 关闭设备连接
void BluetoothDeviceAgent::Close() {
    if (device) {
        device.Close();
        device = nullptr;
    }
    if (gattSession) {
        gattSession.Close();
        gattSession = nullptr;
    }
    // 移除所有特征值变化的事件处理器
    for (const auto& servicePair : valueChangedTokens) {
        for (const auto& characteristicPair : servicePair.second) {
            if (auto iter = gattServicesCharacteristics.find(servicePair.first); iter != gattServicesCharacteristics.end()) {
                if (auto charIter = iter->second.find(characteristicPair.first); charIter != iter->second.end()) {
                    charIter->second.ValueChanged(characteristicPair.second);
                }
            }
        }
    }
}

// 初始化 GATT 会话
IAsyncAction BluetoothDeviceAgent::InitGattSession() {
    if (!gattSession) {
        gattSession = co_await GattSession::FromDeviceIdAsync(device.BluetoothDeviceId());
        // 订阅 MTU 变化事件
        gattSession.MaxPduSizeChanged([this](auto&& sender, auto&& args) {
            if (onMtuChangeCallback) {
                onMtuChangeCallback(sender.MaxPduSize());
            }
        });
    }
    co_return;
}

// 加载所有服务和特征
IAsyncAction BluetoothDeviceAgent::LoadInit() {
    try {
        if (!device) {
            co_return;
        }
        co_await LoadAllServiceAsync();
        // 加载所有服务的特征
        for (const auto& service : gattServices) {
            if (!device) {
                co_return;
            }
            co_await LoadAllCharacteristicAsync(service.first);
        }
    } catch (...) {
        // 忽略异常
    }
}

// 加载所有服务
IAsyncAction BluetoothDeviceAgent::LoadAllServiceAsync() {
    auto serviceResult = co_await device.GetGattServicesAsync();
    if (serviceResult.Status() != GattCommunicationStatus::Success) {
        co_return;
    }
    for (const auto& service : serviceResult.Services()) {
        gattServices.emplace(Utils::to_uuid_hstring(service.Uuid()), service);
    }
}

// 获取服务
IAsyncOperation<GattDeviceService> BluetoothDeviceAgent::GetServiceAsync(const winrt::hstring& service) {
    if (gattServices.count(service) == 0) {
        co_await LoadAllServiceAsync();
    }
    co_return gattServices.at(service);
}

// 加载所有特征
IAsyncAction BluetoothDeviceAgent::LoadAllCharacteristicAsync(const winrt::hstring& service) {
    if (!device) {
        co_return;
    }
    auto gattService = co_await GetServiceAsync(service);
    if (!device) {
        co_return;
    }
    auto characteristicResult = co_await gattService.GetCharacteristicsAsync();
    if (!device) {
        co_return;
    }
    if (characteristicResult.Status() != GattCommunicationStatus::Success) {
        co_return;
    }
    for (const auto& characteristic : characteristicResult.Characteristics()) {
        gattServicesCharacteristics[service].emplace(Utils::to_uuid_hstring(characteristic.Uuid()), characteristic);
    }
}

// 获取特征
IAsyncOperation<GattCharacteristic> BluetoothDeviceAgent::GetCharacteristicAsync(const winrt::hstring& service, const winrt::hstring& characteristic) {
    auto serviceIt = gattServicesCharacteristics.find(service);
    if (serviceIt == gattServicesCharacteristics.end() || serviceIt->second.find(characteristic) == serviceIt->second.end()) {
        co_await LoadAllCharacteristicAsync(service);
        serviceIt = gattServicesCharacteristics.find(service);
        if (serviceIt == gattServicesCharacteristics.end() || serviceIt->second.find(characteristic) == serviceIt->second.end()) {
            throw std::runtime_error("Characteristic not found");
        }
    }
    co_return serviceIt->second.at(characteristic);
}
